package com.s7.recycler.adapter;

import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import com.s7.recycler.R;
import com.s7.recycler.RecyclerCode;
import com.s7.recycler.holder.BaseHolder;
import com.s7.recycler.holder.BaseViewHolder;
import com.s7.recycler.holder.FooterViewHolder;
import com.s7.recycler.holder.LoadErrorHolder;
import com.s7.recycler.holder.LoadViewHolder;
import com.s7.recycler.listener.OnLoadingListener;
import com.s7.recycler.listener.Recycler;

import java.util.ArrayList;
import java.util.List;

/**
 * RecyclerView适配器--加载功能
 * 兼容Grid布局、Linear布局、StaggeredGrid布局
 * @param <T>
 */
public abstract class BaseLoadingAdapter<T> extends CompatRecyclerAdapter<T> {
    
    @NonNull
    @Override
    public BaseHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        if (viewType == RecyclerCode.TYPE_ITEM) {
            View view = getView(parent, getLayoutId());
            return new BaseViewHolder(view);
        }else if (viewType == RecyclerCode.TYPE_LOAD) {
            View view = getView(parent, getLoadId());
            return new LoadViewHolder(view);
        } else if (viewType == RecyclerCode.TYPE_FOOTER) {
            View view = getView(parent, getFooderId());
            return new FooterViewHolder(view);
        }  else {
            View view = getView(parent, getLoadErrorId());
            return new LoadErrorHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(@NonNull BaseHolder holder, int position) {

        holder.setRealPosition(position);

        /*
         * 绑定回调事件
         */
        initListener(holder);

        /*
         * 子类实现数据绑定
         */
        if (holder instanceof BaseViewHolder) {
            initClickListener((BaseViewHolder) holder, datas.get(position));
            ((BaseViewHolder) holder).setData(datas.get(position));
            bindData((BaseViewHolder) holder, position, datas.get(position));
        }

        /*
         * 当显示加载更多时
         */
        if (holder instanceof LoadViewHolder) {
            bindLoad((LoadViewHolder) holder, position);
        }

        /*
         * 当显示底部时
         */
        if (holder instanceof FooterViewHolder) {
            bindFooter((FooterViewHolder) holder, position);
        }

        /*
         * 当显示加载更多失败时
         */
        if (holder instanceof LoadErrorHolder) {
            bindLoadError((LoadErrorHolder) holder, position);
        }
    }


    /**
     * 判断是否添加页面
     * @return
     */
    @Override
    public int getItemCount() {
        if (isLegal() && !isFirst) {
            return datas == null ? 1 : datas.size() + 1;
        }
        return datas == null ? 0 : datas.size();
    }

    /**
     * 判断是否显示添加页
     * @return
     */
    private boolean isLegal() {
        return (isLoad || isFooter || isLoadError);
    }

    @Override
    public int getItemViewType(int position) {

        /*
         * 是否有加载更多
         */
        if (isLoad && position + 1 == getItemCount()) {
            return RecyclerCode.TYPE_LOAD;
        }

        /*
         * 是否没有更多
         */
        if (isFooter && position + 1 == getItemCount()) {
            return RecyclerCode.TYPE_FOOTER;
        }

        /*
         * 是否有加载失败
         */
        if (isLoadError && position + 1 == getItemCount()) {
            return RecyclerCode.TYPE_LOAD_ERROR;
        }

        /*
         * 正常页面
         */
        return RecyclerCode.TYPE_ITEM;
    }

    /**
     *  GridLayoutManager 布局时
     *  当有 footer 时，设置 footer 占满屏幕宽度
     * @param recyclerView
     */
    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager instanceof GridLayoutManager) {
            final GridLayoutManager gridManager = ((GridLayoutManager) manager);
            gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    return isLast(position) ? gridManager.getSpanCount() : 1;
                }
            });
        }
    }

    /**
     * StaggeredGridLayoutManager 布局时
     * 当有 footer 时，设置 footer 占满屏幕宽度
     * @param holder
     */
    @Override
    public void onViewAttachedToWindow(@NonNull BaseHolder holder) {
        super.onViewAttachedToWindow(holder);
        if (isStaggeredGridLayout(holder)) {
            handleLayoutIfStaggeredGridLayout(holder, holder.getLayoutPosition());
        }
    }

    /**
     * 判断当前布局是否是 StaggeredGridLayoutManager 布局
     * @param holder
     * @return
     */
    private boolean isStaggeredGridLayout(RecyclerView.ViewHolder holder) {
        ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
        if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
            return true;
        }
        return false;
    }

    /**
     * 布局是 StaggeredGridLayoutManager 布局
     * 判断 holder 是否是 footer（非正常Item）
     * 当 holder 为 footer 时，设置 holder 占满屏幕宽度
     * @param holder
     * @param position
     */
    private void handleLayoutIfStaggeredGridLayout(RecyclerView.ViewHolder holder, int position) {
        if (isLast(position)){
            ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
            ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);
        }
    }

    /**
     * 是否为 最后一个
     * @param position
     * @return
     */
    private boolean isLast(int position) {
        if (isAadditional) {
            return datas != null && position == datas.size();
        }
        return false;
    }

    /**
     * 获取子item
     *
     * @return
     */
    protected abstract int getLayoutId();

    /**
     * 加载更多
     *
     * @return
     */
    protected int getLoadId() {
        return R.layout.recycler_load;
    }

    /**
     * 加载更多失败
     *
     * @return
     */
    protected int getLoadErrorId() {
        return R.layout.recycler_load_error;
    }

    /**
     * 没有更多
     *
     * @return
     */
    protected int getFooderId() {
        return R.layout.recycler_footer;
    }

    /**
     * 绑定数据
     * @param holder 具体的viewHolder
     * @param data   当前Item的数据
     */
    protected abstract void bindData(BaseViewHolder holder, int position, T data);

    /**
     * 加载更多数据失败
     * @param holder
     * @param position
     */
    protected void bindLoadError(LoadErrorHolder holder, int position) {

    }

    /**
     * 没有更多数据
     *
     * @param holder
     * @param position
     */
    protected void bindFooter(FooterViewHolder holder, int position) {

    }

    /**
     * 加载更多
     *
     * @param holder
     * @param position
     */
    protected void bindLoad(LoadViewHolder holder, int position) {

    }

    private boolean isFirst = true; // 第一次显示数据（避免一进入界面就显示没有更多数据）
    private boolean isAadditional = true; // 是否显示附加页面
    private boolean isLoad = true; // 加载显示状态
    private boolean isFooter = false; // 底部显示状态
    private boolean showLoad = true; // 加载是否显示
    private boolean showFooter = true; // 底部是否显示
    private boolean isLoadError = false; // 加载失败显示状态
    private int num = 100; // 一页最多显示数据
    private OnLoadingListener loadingListener;

    /**
     * 是否显示附加页
     * @param aadditional
     * @return
     */
    public BaseLoadingAdapter setAadditional(boolean aadditional) {
        isAadditional = aadditional;
        return this;
    }

    /**
     * 每页最多显示的数量
     *
     * @param num
     */
    public BaseLoadingAdapter setPageSize(int num) {
        this.num = num;
        return this;
    }

    /**
     * 是否显示加载中
     *
     * @param load
     */
    public BaseLoadingAdapter showLoad(boolean load) {
        if (isAadditional) {
            showLoad = load;
        } else {
            showLoad = false;
        }
        return this;
    }

    /**
     * 是否显示底部
     * @param footer
     */
    public BaseLoadingAdapter showFooter(boolean footer) {
        if (isAadditional) {
            showFooter = footer;
        } else {
            showFooter = false;
        }
        return this;
    }

    public BaseLoadingAdapter setLoadingListener(OnLoadingListener loadingListener) {
        this.loadingListener = loadingListener;
        return this;
    }

    /**
     * 绑定回调事件
     *
     * @param holder
     */
    private void initListener(final BaseHolder holder) {

        /*
         * 加载更多失败
         */
        if (holder instanceof LoadErrorHolder) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    setLoadError(false);
                }
            });
        }

        /*
         * 加载更多
         */
        if (holder instanceof LoadViewHolder) {
            if (loadingListener != null) {
                loadingListener.onLoading();
            }
        }
    }

    /**
     * 设置显示加载失败
     * @param loadError
     * @return
     */
    public BaseLoadingAdapter setLoadError(boolean loadError) {
        initFlag();
        if (!isAadditional) {
            return this;
        }
        isLoadError = loadError;
        isLoad = !isLoadError;
        notifyDataSetChanged();
        return this;
    }

    /**
     * 设置显示没有更多数据
     * @param isNull
     * @return
     */
    public BaseLoadingAdapter setNull(boolean isNull) {
        initFlag();
        if (!isAadditional) {
            return this;
        }
        if (showFooter) {
            isFooter = isNull;
        } else {
            isFooter = showFooter;
        }
        notifyDataSetChanged();
        return this;
    }

    /**
     * 刷新数据（第一次加载数据）
     * @param datas
     */
    public void onRefresh(List<T> datas) {
        initData();
        this.datas.clear();
        if (datas != null) {
            this.datas.addAll(datas);
        }
        isLoad(this.datas);
        notifyDataSetChanged();
    }

    /**
     * 初始化标志
     */
    private void initFlag() {
        isFirst = false;
        if (isAadditional) {
            isLoad = showLoad;
            isLoadError = false;
            isFooter = showFooter;
        } else {
            isLoad = false;
            isLoadError = false;
            isFooter = false;
        }
    }

    /**
     * 判断是否有更多数据
     * @param datas
     */
    private void isLoad(List<T> datas) {
        initFlag();
        if (!isAadditional) {
            return;
        }
        if (datas != null && datas.size() % num == 0 && datas.size() > 0) {
            isLoad = showLoad;
            isFooter = false;
        } else {
            isLoad = false;
            isFooter = showFooter;
        }
    }

    /**
     * 添加数据
     * @param datas
     */
    public void add(List<T> datas) {
        isLoad(datas);
        initData();
        if (datas != null) {
            this.datas.addAll(datas);
            notifyItemRangeInserted(getSize(), datas.size());
        }
    }

    /**
     * 添加数据
     * @param data
     */
    public void add(T data) {
        initData();
        if (data != null) {
            int start = this.datas.size();
            this.datas.add(data);
            notifyItemRangeInserted(start, 1);
        }
    }

    /**
     * 删除指定位置的内容
     * 当集合为空时显示空白页
     * @param position
     */
    public void remove(int position) {
        if (position < this.datas.size()) {
            this.datas.remove(position);
            if (!(this.datas.size() > 0)) {
                isFooter = showFooter;
            }
            notifyDataSetChanged();
        }
    }

}
